- summarize all insights and ideas from the other notebooks, as well as good exploratory plots
name: makeovermonday_2021w22 link: https://data.world/makeovermonday/2021w22 title: 2021/W22: The Plastic Waste Makers Index Data Source: Minderoo
- Production of single-use plastic (SUP) and contribution to single-use plastic waste is estimated and calculated in million metric tons in 2019.
- Rigid packaging is packaging that features heavier and often stronger materials than flexible packaging. Forms of rigid packaging materials include but are not limited to: glass, hard plastics, cardboard, metal, and so on. Rigid packaging supplies are usually more expensive than their flexible alternatives and most have significantly higher carbon footprints than flexible packaging. see https://www.industrialpackaging.com/blog/flexible-vs-rigid-packaging
- Flexible packaging includes all malleable packaging. Some common examples of flexible packaging include shrink film, stretch film, flexible pouches, seal bands, blister or skin packs, and clamshells. In reality, flexible packaging includes any protective packaging made from materials including plastic, paperboard, paper, foil, wax-coated paperboard, and similar materials, or combinations of these materials. see https://www.industrialpackaging.com/blog/flexible-vs-rigid-packaging
- In-scope polymersSingle-use plastics can, in theory, be produced from over a dozen polymer families. However, in 2019, we estimate that close to 90 per cent of all single-use plastics by mass were produced from just five polymers: polypropylene (PP), high-density polyethylene (HDPE), low-density polyethylene (LDPE), linear low-density polyethylene (LLDPE), and polyethylene terephthalate resin (PET) (Figure M2). see https://cdn.minderoo.org/content/uploads/2021/05/18065501/20210518-Plastic-Waste-Makers-Index.pdf
(!) are there two different sub-populations in the data? like two different types of producers with different behavior regarding rigid_format and flexible_format production -> may be there are producers with only rigid format -> if group is identified, then add a variable to tag them and make the plots again with group coloring, I wonder if there are also the producers with total_waste_div_production ration 1.0
head(plastic)
summary(plastic)
rank polymer_producer no_of_assets production_of_in_scope_polymers flexible_format_contribution_to_sup_waste rigid_format_contribution_to_sup_waste
Min. : 1.00 Length:100 Min. : 0.00 Min. : 0.200 Min. :0.000 Min. :0.000
1st Qu.: 25.75 Class :character 1st Qu.: 3.00 1st Qu.: 0.500 1st Qu.:0.100 1st Qu.:0.100
Median : 50.50 Mode :character Median : 6.00 Median : 0.900 Median :0.200 Median :0.200
Mean : 50.50 Mean :11.56 Mean : 1.805 Mean :0.538 Mean :0.416
3rd Qu.: 75.25 3rd Qu.:12.25 3rd Qu.: 1.700 3rd Qu.:0.500 3rd Qu.:0.500
Max. :100.00 Max. :82.00 Max. :11.600 Max. :4.700 Max. :4.500
total_contribution_to_sup_waste total_waste_div_production
Min. :0.200 Min. :0.3000
1st Qu.:0.300 1st Qu.:0.4300
Median :0.450 Median :0.5000
Mean :0.950 Mean :0.5834
3rd Qu.:0.925 3rd Qu.:0.6900
Max. :5.900 Max. :1.0000
| observations from clean nb |
- columns: rank numeric, ordered, unique, can serve as identifier, rank of producer according to index polymer_producer string, unique identifier, name of producer no_of_assets numeric, metric, number of assets of the producer production_of_in_scope_polymers numeric, metric in million metric tons, production of plolymers that are in-scope of preceding analysis flexible_format_contribution_to_sup_waste numeric, metric in million metric tons, flexible form of contribution to sup waste rigid_format_contribution_to_sup_waste numeric, metric in million metric tons, rigid form of contribution to sup waste total_contribution_to_sup_waste numeric, metric in million metric tons, total contribution is the sum of flexible and rigid
- no missing values at all, also it is a very small dataset
- no duplicated rows
- no changes were made to data set
| insights from describe uni |
- no_of_assets is poisson distributed, where most producer only have up to 9 (median = 6) assets, some have up to 29 (upper fence = 26), and only a few (outliers) are above that with up to 82 assets
- production_of_in_scope_polymers is poisson distributed, likes very similar to no_of_assets, median is 0.9, upper fence is 3.4, max is 11.6 -> might correlate with no_of_assets?
- flexible_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.7
- rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.5, very similar to flexible_format_contribution_to_sup_waste, but with less outliers
- rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets (again), median is 0.45, upper fence is 1.9, max is 5.9 is sum of flexible_form + rigid_form
- ration of sup_waste to produced polymers is between min 0.3 and max 1.0 and has median 0.5, most data lies between 0.4 and 0.6, but there is a high spike at 1.0 (with count 15)
- comparing rigid_format and flexible_format shows that up to the upper fence 1.1, the distribution is similar, but there are more bigger (>3) outliers in flexible
# one variable, continuous x, show distribution
name = 'total_contribution_to_sup_waste'
df <- plastic %>% rename(value = total_contribution_to_sup_waste) %>% select(value)
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = value)) +
# geom_density() +
geom_histogram(binwidth = 0.1) +
# geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
boxplot <- df %>%
ggplot(aes(x = 1, y = value)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("distribution of", name, sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = value)) +
geom_qq(alpha = 0.5) +
geom_qq_line() +
coord_flip() +
theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) %>% layout(xaxis = list(title = name))
fig
# two variables, both continuous x, compare distributions
name = c('flexible_format_contribution_to_sup_waste', 'rigid_format_contribution_to_sup_waste')
df <- plastic %>% rename(flexible = flexible_format_contribution_to_sup_waste, rigid = rigid_format_contribution_to_sup_waste) %>% select(flexible, rigid) %>% pivot_longer(cols = c(flexible,rigid))
boxplot <- df %>%
ggplot(aes(x = name, y = value, colour = name)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("compare ", name[1], "and", name[2], sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = value, fill = name)) +
# geom_density() +
geom_histogram(binwidth = 0.1, alpha = 0.5, position = "identity") +
# geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1, dotsize = 0.23, binwidth = 0.1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = value, colour = name)) +
geom_qq(alpha = 0.5) +
geom_qq_line(alpha = 0.5) +
coord_flip() +
theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) %>% layout(xaxis = list(title = paste(name[1], "<br>", name[2], sep="")))
fig
| insights from describe multi |
- no_of_assets over rank increases only slowly until rank 25, afterwards it starts to increase strongly (compared to before), this is where the outliers come in from no_of_assets distribution, but most assets in not rank 1
- production_of_in_scope_polymers over rank starts to increase again substantially after about rank 25
- flexible_format_contribution_to_sup_waste over rank starts to increase again substantially after about rank 25, there are a couple of producers above rank 25 which do not produce flexible_format (like outliers), the spread is very high towards the end
- rigid_format_contribution_to_sup_waste over rank starts to increase again substantially after about rank 25, but compared to flexible_format the spread is not as high (except for one outlier, which is also really low on flexible format), but overall there is less production in rigid_format
- total_contribution_to_sup_waste over rank, seems to be oddly stepped, but that is because the rank is directly determined by the total_contribution (there are not independent), again the steep increase starts at rank 25
- low no_of_assets seems to also imply low production_of_in_scope_polymers, which is for like 80% of the producers the case, but after no_of_assets bigger 20, there is in almost linear increase of production with no_of_assets
- total_waste_div_production over rank ranges from 0.3 to 1.0 and is in general like 0.5 (but this we already saw in univariate analysis), the spread is high across all rank, but there is like a very empty band between 0.6 and 0.9 where only 7 producers are
- flexible_format_contribution_to_sup_waste over no_of_assets shows similar picture as production over assets, but with wider spread for assets > 20
- rigid_format_contribution_to_sup_waste over no_of_assets is surprisingly different from flexible_format over assets, as it is in the beginning more spread toward higher contribution, but after assets > 20, there seems to be a threshold at 1.4, where only a few outliers go beyond, though it is rising until this (fast reached) point
- total_contribution_to_sup_waste over no_of_assets does again look similar to flexible_format over assets, since total = flexible + rigid, this means that above 20 assets, flexible is dominant, but below there is a wider spread due to rigid_format
- total_waste_div_production over no_of_assets show at low number of assets (<20) a wide spread ranging from 0.3 to 1.0, but above there seems to be stable at around 0.45 ratio -> maybe there are two different sub-populations behind?
- with a bigger production_of_in_scope_polymers comes relatively linearly a bigger flexible_format_contribution_to_sup_waste, but most producer have a smaller 3
- rigid_format_contribution_to_sup_waste over production_of_in_scope_polymers shows again the cap in rigid_format part not growing beyond 1.3 with production, but also a second tendency in the beginning where a linear behavior of strong growing rigid_format suggest that there might be two sub-populations
- total_contribution_to_sup_waste over production_of_in_scope_polymers looks pretty much linear, with a bulk of data points below production < 3
- in total_waste_div_production over production_of_in_scope_polymers below production < 3 there are two cluster around 0.45 and 1.0, beyond production > 3 it seems to be stable at 0.5
- rigid_format_contribution_to_sup_waste over flexible_format_contribution_to_sup_waste shows the previously observed phänomena, i) with growing flexible_format, rigid_format also start to grow a little but then stays at around 1.2, ii) there is one group that only grows in rigid_format and produce almost no flexible_format
- flexible_format_contribution_to_sup_waste over total_contribution_to_sup_waste shows an almost linear increase in flexible_format with total_contribution, but here again we have a group with almost no flexible_format (which means that they only produce rigid_format)
- total_waste_div_production over flexible_format_contribution_to_sup_waste shows agani tqwo clusters one around total_waste_div 1.0 and the other around 0.45, and that the higher regions of flexible_format are only ovvupied by a few producers with a ration around 0.47
- rigid_format_contribution_to_sup_waste over total_contribution_to_sup_waste only at the beginning rigid format is growing with total_contribution, but it is not really growing beyond 1.3, for the rigid_format only group, there there is a almost linear group
- most data points lie in the range total_waste_div < 0.7 and rigid_format < 0.5, for the outliers there are two groups one around ratio 1.0 and one with lower ratio around 0.5
- total_waste_div_production over total_contribution_to_sup_waste shows again two groups around 1.0 and 0.45 and a concentration under 0.75 total_contribution
- comparing flexible_format and rigid_format over production shows us that flexible_format is growing linearly while rigid stops growing linearly mid way at production = 6, but this growth might be disturbed by two different sub-populations and is expected to be much less strong and capping out earlier
# two variables, continuous x, continuous y, show trend and distribution
name = c('production_of_in_scope_polymers', 'total_contribution_to_sup_waste')
df <- plastic %>% rename(x = production_of_in_scope_polymers, y = total_contribution_to_sup_waste, text = polymer_producer) %>% select(x, y, text)
# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
ggplot(aes(x = x, y = y)) +
# geom_jitter(alpha = 0.5, size = 1) +
geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
geom_point(aes(text = text), alpha = 0.75) + # point geom is used to create scatterplots
theme_minimal() +
ggtitle(paste("trend of", name[2], "over", name[1], sep=" "))
Ignoring unknown aesthetics: text
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
ggplot(aes(x = x)) +
stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
# geom_histogram(binwidth = 1) +
theme_minimal()
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))
y_density_plot <- df %>%
ggplot(aes(x = y)) +
stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
# geom_histogram(binwidth = 1) +
coord_flip() +
theme_minimal()
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
ggplot(aes(x = x, y = y)) +
geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
theme_minimal()
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
Based on info supplied, a 'scatter' trace seems appropriate.
Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
Based on info supplied, a 'scatter' trace seems appropriate.
Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = name[2]))
Can only have one: config
fig
# three variables, continuous x, two continuous y, show trend and distribution
name = c('production_of_in_scope_polymers', 'rigid_format_contribution_to_sup_waste', 'flexible_format_contribution_to_sup_waste')
df <- plastic %>% rename(x = production_of_in_scope_polymers, rigid = rigid_format_contribution_to_sup_waste, flexible = flexible_format_contribution_to_sup_waste) %>% select(x, rigid, flexible) %>% pivot_longer(cols = c(flexible,rigid)) %>% rename(y = value)
# https://ggplot2.tidyverse.org/reference/geom_smooth.html
point_plot <- df %>%
ggplot(aes(x = x, y = y, colour = name)) +
# geom_jitter(alpha = 0.5, size = 1) +
geom_rug(alpha = 0.5) + # two 1d marginal distributions, display individual cases so are best used with smaller datasets
geom_density_2d(alpha = 0.2, bins = 4) +# 2D kernel density estimation using MASS::kde2d() and display the results with contours
geom_smooth(fill = "grey90") + # aids the eye in seeing patterns in the presence of overplotting
geom_point(alpha = 0.75) + # point geom is used to create scatterplots
theme_minimal() +
ggtitle(paste("trend of", name[2], "over", name[1], sep=" "))
point_plot <- ggplotly(point_plot) %>% layout(xaxis = list(showticklabels = FALSE))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
x_density_plot <- df %>%
ggplot(aes(x = x, colour = name)) +
stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
# geom_histogram(binwidth = 1) +
theme_minimal()
x_density_plot <- ggplotly(x_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))
y_density_plot <- df %>%
ggplot(aes(x = y, colour = name)) +
stat_density(geom="line") + # draws kernel density estimate, which is a smoothed version of the histogram
# geom_histogram(binwidth = 1) +
coord_flip() +
theme_minimal()
y_density_plot <- ggplotly(y_density_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_quantile.html
qualtile_plot <- df %>%
ggplot(aes(x = x, y = y, colour = name)) +
geom_quantile(alpha = 0.8) + # fits a quantile regression to the data and draws the fitted quantiles with lines
theme_minimal()
qualtile_plot <- ggplotly(qualtile_plot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
Smoothing formula not specified. Using: y ~ x
Smoothing formula not specified. Using: y ~ x
# merge figures into one plot, via subplots, https://plotly-r.com/arranging-views.html
sub1 <- subplot(x_density_plot, plotly_empty(), point_plot, y_density_plot, nrows = 2, margin = 0, heights = c(0.15, 0.85), widths = c(0.9, 0.1), shareX = TRUE, shareY = TRUE, titleX = FALSE, titleY = FALSE) %>% layout() %>% hide_legend()
No trace type specified and no positional attributes specifiedNo trace type specified:
Based on info supplied, a 'scatter' trace seems appropriate.
Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
sub2 <- subplot(qualtile_plot, plotly_empty(), margin = 0, widths = c(0.9, 0.10), titleX = FALSE, titleY = FALSE) %>% layout()
No trace type specified and no positional attributes specifiedNo trace type specified:
Based on info supplied, a 'scatter' trace seems appropriate.
Read more about this trace type -> https://plotly.com/r/reference/#scatter
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Can only have one: config
fig <- subplot(sub1, sub2, nrows = 2, margin = 0, heights = c(0.8, 0.2), shareX = TRUE) %>% layout(xaxis = list(title = name[1]), yaxis = list(title = paste(name[2], "<br>", name[3], sep="")))
Can only have one: config
fig
LS0tDQp0aXRsZTogInN1bW1hcnkgZm9yIHBsYXN0aWMgd2FzdGUgbWFrZXJzIGluZGV4IGRhdGEiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQotLS0NCnB1cnBvc2Ugb2Ygbm90ZWJvb2sNCi0tLQ0KDQogIChpKSBzdW1tYXJpemUgYWxsIGluc2lnaHRzIGFuZCBpZGVhcyBmcm9tIHRoZSBvdGhlciBub3RlYm9va3MsIGFzIHdlbGwgYXMgZ29vZCBleHBsb3JhdG9yeSBwbG90cw0KICANCi0tLQ0KaW5mb3JtYXRpb24NCi0tLQ0KDQpuYW1lOiBtYWtlb3Zlcm1vbmRheV8yMDIxdzIyDQpsaW5rOiBodHRwczovL2RhdGEud29ybGQvbWFrZW92ZXJtb25kYXkvMjAyMXcyMg0KdGl0bGU6IDIwMjEvVzIyOiBUaGUgUGxhc3RpYyBXYXN0ZSBNYWtlcnMgSW5kZXgNCkRhdGEgU291cmNlOiBbTWluZGVyb29dKGh0dHBzOi8vd3d3Lm1pbmRlcm9vLm9yZy9wbGFzdGljLXdhc3RlLW1ha2Vycy1pbmRleC9kYXRhL2luZGljZXMvcHJvZHVjZXJzLykNCg0KDQotLS0NCmRvbWFpbiBpbmZvcm1hdGlvbiANCi0tLQ0KDQogKGkpIFByb2R1Y3Rpb24gb2Ygc2luZ2xlLXVzZSBwbGFzdGljIChTVVApIGFuZCBjb250cmlidXRpb24gdG8gc2luZ2xlLXVzZSBwbGFzdGljIHdhc3RlIGlzIGVzdGltYXRlZCBhbmQgY2FsY3VsYXRlZCBpbiBtaWxsaW9uIG1ldHJpYyB0b25zIGluIDIwMTkuDQogKGkpIFJpZ2lkIHBhY2thZ2luZyBpcyBwYWNrYWdpbmcgdGhhdCBmZWF0dXJlcyBoZWF2aWVyIGFuZCBvZnRlbiBzdHJvbmdlciBtYXRlcmlhbHMgdGhhbiBmbGV4aWJsZSBwYWNrYWdpbmcuIEZvcm1zIG9mIHJpZ2lkIHBhY2thZ2luZyBtYXRlcmlhbHMgaW5jbHVkZSBidXQgYXJlIG5vdCBsaW1pdGVkIHRvOiBnbGFzcywgICAgICBoYXJkIHBsYXN0aWNzLCBjYXJkYm9hcmQsIG1ldGFsLCBhbmQgc28gb24uIFJpZ2lkIHBhY2thZ2luZyBzdXBwbGllcyBhcmUgdXN1YWxseSBtb3JlIGV4cGVuc2l2ZSB0aGFuIHRoZWlyIGZsZXhpYmxlIGFsdGVybmF0aXZlcyBhbmQgbW9zdCBoYXZlIHNpZ25pZmljYW50bHkgaGlnaGVyIGNhcmJvbiAgICAgICAgICAgICAgZm9vdHByaW50cyB0aGFuIGZsZXhpYmxlIHBhY2thZ2luZy4gc2VlIGh0dHBzOi8vd3d3LmluZHVzdHJpYWxwYWNrYWdpbmcuY29tL2Jsb2cvZmxleGlibGUtdnMtcmlnaWQtcGFja2FnaW5nDQogKGkpIEZsZXhpYmxlIHBhY2thZ2luZyBpbmNsdWRlcyBhbGwgbWFsbGVhYmxlIHBhY2thZ2luZy4gU29tZSBjb21tb24gZXhhbXBsZXMgb2YgZmxleGlibGUgcGFja2FnaW5nIGluY2x1ZGUgc2hyaW5rIGZpbG0sIHN0cmV0Y2ggZmlsbSwgZmxleGlibGUgcG91Y2hlcywgc2VhbCBiYW5kcywgYmxpc3RlciBvciBza2luICAgICAgICBwYWNrcywgYW5kIGNsYW1zaGVsbHMuIEluIHJlYWxpdHksIGZsZXhpYmxlIHBhY2thZ2luZyBpbmNsdWRlcyBhbnkgcHJvdGVjdGl2ZSBwYWNrYWdpbmcgbWFkZSBmcm9tIG1hdGVyaWFscyBpbmNsdWRpbmcgcGxhc3RpYywgcGFwZXJib2FyZCwgcGFwZXIsIGZvaWwsIHdheC1jb2F0ZWQgcGFwZXJib2FyZCwgYW5kICAgICAgc2ltaWxhciBtYXRlcmlhbHMsIG9yIGNvbWJpbmF0aW9ucyBvZiB0aGVzZSBtYXRlcmlhbHMuIHNlZSBodHRwczovL3d3dy5pbmR1c3RyaWFscGFja2FnaW5nLmNvbS9ibG9nL2ZsZXhpYmxlLXZzLXJpZ2lkLXBhY2thZ2luZw0KIChpKSBJbi1zY29wZSBwb2x5bWVyc1NpbmdsZS11c2UgcGxhc3RpY3MgY2FuLCBpbiB0aGVvcnksIGJlIHByb2R1Y2VkIGZyb20gb3ZlciBhIGRvemVuIHBvbHltZXIgZmFtaWxpZXMuIEhvd2V2ZXIsIGluIDIwMTksIHdlIGVzdGltYXRlIHRoYXQgY2xvc2UgdG8gOTAgcGVyIGNlbnQgb2YgYWxsIHNpbmdsZS11c2UgICAgICAgICAgcGxhc3RpY3MgYnkgbWFzcyB3ZXJlIHByb2R1Y2VkIGZyb20ganVzdCBmaXZlIHBvbHltZXJzOiBwb2x5cHJvcHlsZW5lIChQUCksIGhpZ2gtZGVuc2l0eSBwb2x5ZXRoeWxlbmUgKEhEUEUpLCBsb3ctZGVuc2l0eSBwb2x5ZXRoeWxlbmUgKExEUEUpLCBsaW5lYXIgbG93LWRlbnNpdHkgcG9seWV0aHlsZW5lICAgICAgICAgIChMTERQRSksIGFuZCBwb2x5ZXRoeWxlbmUgdGVyZXBodGhhbGF0ZSByZXNpbiAoUEVUKSAoRmlndXJlIE0yKS4gc2VlIGh0dHBzOi8vY2RuLm1pbmRlcm9vLm9yZy9jb250ZW50L3VwbG9hZHMvMjAyMS8wNS8xODA2NTUwMS8yMDIxMDUxOC1QbGFzdGljLVdhc3RlLU1ha2Vycy1JbmRleC5wZGYNCiAgDQotLS0NCnN1bW1hcnkgaGlnaGxpZ2h0cw0KLS0tDQogIA0KDQoNCi0tLQ0Kc3Rvcmllcw0KLS0tDQoNCiAgKCEpIGFyZSB0aGVyZSB0d28gZGlmZmVyZW50IHN1Yi1wb3B1bGF0aW9ucyBpbiB0aGUgZGF0YT8gbGlrZSB0d28gZGlmZmVyZW50IHR5cGVzIG9mIHByb2R1Y2VycyB3aXRoIGRpZmZlcmVudCBiZWhhdmlvciByZWdhcmRpbmcgcmlnaWRfZm9ybWF0IGFuZCBmbGV4aWJsZV9mb3JtYXQgcHJvZHVjdGlvbiANCiAgICAgIC0+IG1heSBiZSB0aGVyZSBhcmUgcHJvZHVjZXJzIHdpdGggb25seSByaWdpZCBmb3JtYXQNCiAgICAgIC0+IGlmIGdyb3VwIGlzIGlkZW50aWZpZWQsIHRoZW4gYWRkIGEgdmFyaWFibGUgdG8gdGFnIHRoZW0gYW5kIG1ha2UgdGhlIHBsb3RzIGFnYWluIHdpdGggZ3JvdXAgY29sb3JpbmcsIEkgd29uZGVyIGlmIHRoZXJlIGFyZSBhbHNvIHRoZSBwcm9kdWNlcnMgd2l0aCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfd2FzdGVfZGl2X3Byb2R1Y3Rpb24gcmF0aW9uIDEuMCANCg0KLS0tDQpsb2FkIHBhY2thZ2VzDQotLS0NCmBgYHtyIGxvYWQgcGFja2FnZXMsIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpICMgdGlkeSBkYXRhIGZyYW1lDQpsaWJyYXJ5KHBsb3RseSkgIyBtYWtlIGdncGxvdHMgaW50ZXJhY3RpdmUNCmBgYA0KDQotLS0NCm92ZXJ2aWV3DQotLS0NCmBgYHtyfQ0KaGVhZChwbGFzdGljKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeShwbGFzdGljKQ0KYGBgDQoNCi0tLQ0Kb2JzZXJ2YXRpb25zIGZyb20gY2xlYW4gbmINCi0tLQ0KDQogIChpKSBjb2x1bW5zOiByYW5rICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1lcmljLCBvcmRlcmVkLCB1bmlxdWUsIGNhbiBzZXJ2ZSBhcyBpZGVudGlmaWVyLCByYW5rIG9mIHByb2R1Y2VyIGFjY29yZGluZyB0byBpbmRleA0KICAgICAgICAgICAgICAgcG9seW1lcl9wcm9kdWNlciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nLCB1bmlxdWUgaWRlbnRpZmllciwgbmFtZSBvZiBwcm9kdWNlcg0KICAgICAgICAgICAgICAgbm9fb2ZfYXNzZXRzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtZXJpYywgbWV0cmljLCBudW1iZXIgb2YgYXNzZXRzIG9mIHRoZSBwcm9kdWNlcg0KICAgICAgICAgICAgICAgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyAgICAgICAgICAgICAgbnVtZXJpYywgbWV0cmljIGluIG1pbGxpb24gbWV0cmljIHRvbnMsIHByb2R1Y3Rpb24gb2YgcGxvbHltZXJzIHRoYXQgYXJlIGluLXNjb3BlIG9mIHByZWNlZGluZyBhbmFseXNpcw0KICAgICAgICAgICAgICAgZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgICAgbnVtZXJpYywgbWV0cmljIGluIG1pbGxpb24gbWV0cmljIHRvbnMsIGZsZXhpYmxlIGZvcm0gb2YgY29udHJpYnV0aW9uIHRvIHN1cCB3YXN0ZQ0KICAgICAgICAgICAgICAgcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgICAgICAgbnVtZXJpYywgbWV0cmljIGluIG1pbGxpb24gbWV0cmljIHRvbnMsIHJpZ2lkIGZvcm0gb2YgY29udHJpYnV0aW9uIHRvIHN1cCB3YXN0ZQ0KICAgICAgICAgICAgICAgdG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSAgICAgICAgICAgICAgbnVtZXJpYywgbWV0cmljIGluIG1pbGxpb24gbWV0cmljIHRvbnMsIHRvdGFsIGNvbnRyaWJ1dGlvbiBpcyB0aGUgc3VtIG9mIGZsZXhpYmxlIGFuZCByaWdpZA0KICAoaSkgbm8gbWlzc2luZyB2YWx1ZXMgYXQgYWxsLCBhbHNvIGl0IGlzIGEgdmVyeSBzbWFsbCBkYXRhc2V0DQogIChpKSBubyBkdXBsaWNhdGVkIHJvd3MNCiAgKGkpIG5vIGNoYW5nZXMgd2VyZSBtYWRlIHRvIGRhdGEgc2V0DQoNCi0tLQ0KaW5zaWdodHMgZnJvbSBkZXNjcmliZSB1bmkNCi0tLQ0KDQogIChpKSBub19vZl9hc3NldHMgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgd2hlcmUgbW9zdCBwcm9kdWNlciBvbmx5IGhhdmUgdXAgdG8gOSAobWVkaWFuID0gNikgYXNzZXRzLCBzb21lIGhhdmUgdXAgdG8gMjkgKHVwcGVyIGZlbmNlID0gMjYpLCBhbmQgb25seSBhIGZldyAob3V0bGllcnMpIGFyZSBhYm92ZSB0aGF0ICAgICAgICB3aXRoIHVwIHRvIDgyIGFzc2V0cw0KICAoaSkgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyBpcyBwb2lzc29uIGRpc3RyaWJ1dGVkLCBsaWtlcyB2ZXJ5IHNpbWlsYXIgdG8gbm9fb2ZfYXNzZXRzLCBtZWRpYW4gaXMgMC45LCB1cHBlciBmZW5jZSBpcyAzLjQsIG1heCBpcyAxMS42DQogICAgICAtPiBtaWdodCBjb3JyZWxhdGUgd2l0aCBub19vZl9hc3NldHM/DQogIChpKSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBpcyBwb2lzc29uIGRpc3RyaWJ1dGVkLCBsaWtlcyB2ZXJ5IHNpbWlsYXIgdG8gbm9fb2ZfYXNzZXRzLCBtZWRpYW4gaXMgMC4yLCB1cHBlciBmZW5jZSBpcyAxLjEsIG1heCBpcyA0LjcNCiAgKGkpIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIGlzIHBvaXNzb24gZGlzdHJpYnV0ZWQsIGxpa2VzIHZlcnkgc2ltaWxhciB0byBub19vZl9hc3NldHMsIG1lZGlhbiBpcyAwLjIsIHVwcGVyIGZlbmNlIGlzIDEuMSwgbWF4IGlzIDQuNSwNCiAgICAgIHZlcnkgc2ltaWxhciB0byBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSwgYnV0IHdpdGggbGVzcyBvdXRsaWVycw0KICAoaSkgcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgbGlrZXMgdmVyeSBzaW1pbGFyIHRvIG5vX29mX2Fzc2V0cyAoYWdhaW4pLCBtZWRpYW4gaXMgMC40NSwgdXBwZXIgZmVuY2UgaXMgMS45LCBtYXggaXMgNS45DQogICAgICBpcyBzdW0gb2YgZmxleGlibGVfZm9ybSArIHJpZ2lkX2Zvcm0NCiAgKGkpIHJhdGlvbiBvZiBzdXBfd2FzdGUgdG8gcHJvZHVjZWQgcG9seW1lcnMgaXMgYmV0d2VlbiBtaW4gMC4zIGFuZCBtYXggMS4wIGFuZCBoYXMgbWVkaWFuIDAuNSwgbW9zdCBkYXRhIGxpZXMgYmV0d2VlbiAwLjQgYW5kIDAuNiwgYnV0IHRoZXJlIGlzIGEgaGlnaCBzcGlrZSBhdCAxLjAgKHdpdGggY291bnQgMTUpDQogIChpKSBjb21wYXJpbmcgcmlnaWRfZm9ybWF0IGFuZCBmbGV4aWJsZV9mb3JtYXQgc2hvd3MgdGhhdCB1cCB0byB0aGUgdXBwZXIgZmVuY2UgMS4xLCB0aGUgZGlzdHJpYnV0aW9uIGlzIHNpbWlsYXIsIGJ1dCB0aGVyZSBhcmUgbW9yZSBiaWdnZXIgKD4zKSBvdXRsaWVycyBpbiBmbGV4aWJsZQ0KDQpgYGB7cn0NCiMgb25lIHZhcmlhYmxlLCBjb250aW51b3VzIHgsIHNob3cgZGlzdHJpYnV0aW9uDQpuYW1lID0gJ3RvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUodmFsdWUgPSB0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlKSAlPiUgc2VsZWN0KHZhbHVlKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX2RvdHBsb3QuaHRtbA0KZG90cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gdmFsdWUpKSArDQogICAgIyBnZW9tX2RlbnNpdHkoKSArDQogICAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjEpICsNCiAgICAjIGdlb21fZG90cGxvdChtZXRob2Q9Imhpc3RvZG90Iiwgc3RhY2tncm91cHMgPSBUUlVFLCBzdGFja3JhdGlvID0gMS4xLCBkb3RzaXplID0gMS4yLCBiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmRvdHBsb3QgPC0gZ2dwbG90bHkoZG90cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCmJveHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IDEsIHkgPSB2YWx1ZSkpICsNCiAgICBnZW9tX2JveHBsb3QoKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGdndGl0bGUocGFzdGUoImRpc3RyaWJ1dGlvbiBvZiIsIG5hbWUsIHNlcD0iICIpKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KYm94cGxvdCA8LSBnZ3Bsb3RseShib3hwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xcS5odG1sIA0KcGxvdF9xcSA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSB2YWx1ZSkpICsNCiAgICBnZW9tX3FxKGFscGhhID0gMC41KSArDQogICAgZ2VvbV9xcV9saW5lKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpDQpwbG90X3FxIDwtIGdncGxvdGx5KHBsb3RfcXEpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0KZmlnIDwtIHN1YnBsb3QoZG90cGxvdCwgYm94cGxvdCwgcGxvdF9xcSwgbnJvd3MgPSAzLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjUsIDAuMiwgMC4zKSwgc2hhcmVYID0gVFJVRSkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lKSkNCg0KZmlnDQpgYGANCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBib3RoIGNvbnRpbnVvdXMgeCwgY29tcGFyZSBkaXN0cmlidXRpb25zDQpuYW1lID0gYygnZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnLCAncmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnKQ0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKGZsZXhpYmxlID0gZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUsIHJpZ2lkID0gcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUpICU+JSBzZWxlY3QoZmxleGlibGUsIHJpZ2lkKSAlPiUgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGZsZXhpYmxlLHJpZ2lkKSkNCg0KYm94cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gbmFtZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBuYW1lKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgiY29tcGFyZSAiLCBuYW1lWzFdLCAiYW5kIiwgbmFtZVsyXSwgc2VwPSIgIikpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpib3hwbG90IDwtIGdncGxvdGx5KGJveHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX2RvdHBsb3QuaHRtbA0KZG90cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gdmFsdWUsIGZpbGwgPSBuYW1lKSkgKw0KICAgICMgZ2VvbV9kZW5zaXR5KCkgKw0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xLCBhbHBoYSA9IDAuNSwgcG9zaXRpb24gPSAiaWRlbnRpdHkiKSArDQogICAgIyBnZW9tX2RvdHBsb3QobWV0aG9kPSJoaXN0b2RvdCIsIHN0YWNrZ3JvdXBzID0gVFJVRSwgc3RhY2tyYXRpbyA9IDEsIGRvdHNpemUgPSAwLjIzLCBiaW53aWR0aCA9IDAuMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KZG90cGxvdCA8LSBnZ3Bsb3RseShkb3RwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xcS5odG1sIA0KcGxvdF9xcSA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSB2YWx1ZSwgY29sb3VyID0gbmFtZSkpICsNCiAgICBnZW9tX3FxKGFscGhhID0gMC41KSArDQogICAgZ2VvbV9xcV9saW5lKGFscGhhID0gMC41KSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQpwbG90X3FxIDwtIGdncGxvdGx5KHBsb3RfcXEpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0KZmlnIDwtIHN1YnBsb3QoZG90cGxvdCwgYm94cGxvdCwgcGxvdF9xcSwgbnJvd3MgPSAzLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjUsIDAuMiwgMC4zKSwgc2hhcmVYID0gVFJVRSkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZShuYW1lWzFdLCAiPGJyPiIsIG5hbWVbMl0sIHNlcD0iIikpKQ0KDQpmaWcNCmBgYA0KDQotLS0NCmluc2lnaHRzIGZyb20gZGVzY3JpYmUgbXVsdGkNCi0tLQ0KDQogIChpKSBub19vZl9hc3NldHMgb3ZlciByYW5rIGluY3JlYXNlcyBvbmx5IHNsb3dseSB1bnRpbCByYW5rIDI1LCBhZnRlcndhcmRzIGl0IHN0YXJ0cyB0byBpbmNyZWFzZSBzdHJvbmdseSAoY29tcGFyZWQgdG8gYmVmb3JlKSwgdGhpcyBpcyB3aGVyZSB0aGUgb3V0bGllcnMgY29tZSBpbiBmcm9tIG5vX29mX2Fzc2V0cyAgICAgICBkaXN0cmlidXRpb24sIGJ1dCBtb3N0IGFzc2V0cyBpbiBub3QgcmFuayAxDQogIChpKSBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzIG92ZXIgcmFuayBzdGFydHMgdG8gaW5jcmVhc2UgYWdhaW4gc3Vic3RhbnRpYWxseSBhZnRlciBhYm91dCByYW5rIDI1DQogIChpKSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBvdmVyIHJhbmsgc3RhcnRzIHRvIGluY3JlYXNlIGFnYWluIHN1YnN0YW50aWFsbHkgYWZ0ZXIgYWJvdXQgcmFuayAyNSwgdGhlcmUgYXJlIGEgY291cGxlIG9mIHByb2R1Y2VycyBhYm92ZSByYW5rIDI1IHdoaWNoIGRvIG5vdCAgICAgICAgICAgIHByb2R1Y2UgZmxleGlibGVfZm9ybWF0IChsaWtlIG91dGxpZXJzKSwgdGhlIHNwcmVhZCBpcyB2ZXJ5IGhpZ2ggdG93YXJkcyB0aGUgZW5kDQogIChpKSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBvdmVyIHJhbmsgc3RhcnRzIHRvIGluY3JlYXNlIGFnYWluIHN1YnN0YW50aWFsbHkgYWZ0ZXIgYWJvdXQgcmFuayAyNSwgYnV0IGNvbXBhcmVkIHRvIGZsZXhpYmxlX2Zvcm1hdCB0aGUgc3ByZWFkIGlzIG5vdCBhcyBoaWdoIChleGNlcHQgICAgICAgIGZvciBvbmUgb3V0bGllciwgd2hpY2ggaXMgYWxzbyByZWFsbHkgbG93IG9uIGZsZXhpYmxlIGZvcm1hdCksIGJ1dCBvdmVyYWxsIHRoZXJlIGlzIGxlc3MgcHJvZHVjdGlvbiBpbiByaWdpZF9mb3JtYXQNCiAgKGkpIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciByYW5rLCBzZWVtcyB0byBiZSBvZGRseSBzdGVwcGVkLCBidXQgdGhhdCBpcyBiZWNhdXNlIHRoZSByYW5rIGlzIGRpcmVjdGx5IGRldGVybWluZWQgYnkgdGhlIHRvdGFsX2NvbnRyaWJ1dGlvbiAodGhlcmUgYXJlIG5vdCBpbmRlcGVuZGVudCksICAgICAgIGFnYWluIHRoZSBzdGVlcCBpbmNyZWFzZSBzdGFydHMgYXQgcmFuayAyNSANCiAgKGkpIGxvdyBub19vZl9hc3NldHMgc2VlbXMgdG8gYWxzbyBpbXBseSBsb3cgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycywgd2hpY2ggaXMgZm9yIGxpa2UgODAlIG9mIHRoZSBwcm9kdWNlcnMgdGhlIGNhc2UsIGJ1dCBhZnRlciBub19vZl9hc3NldHMgYmlnZ2VyIDIwLCB0aGVyZSBpcyBpbiBhbG1vc3QgICAgICAgbGluZWFyIGluY3JlYXNlIG9mIHByb2R1Y3Rpb24gd2l0aCBub19vZl9hc3NldHMNCiAgKGkpIHRvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uIG92ZXIgcmFuayByYW5nZXMgZnJvbSAwLjMgdG8gMS4wIGFuZCBpcyBpbiBnZW5lcmFsIGxpa2UgMC41IChidXQgdGhpcyB3ZSBhbHJlYWR5IHNhdyBpbiB1bml2YXJpYXRlIGFuYWx5c2lzKSwgdGhlIHNwcmVhZCBpcyBoaWdoIGFjcm9zcyBhbGwgcmFuaywgYnV0ICAgICAgIHRoZXJlIGlzIGxpa2UgYSB2ZXJ5IGVtcHR5IGJhbmQgYmV0d2VlbiAwLjYgYW5kIDAuOSB3aGVyZSBvbmx5IDcgcHJvZHVjZXJzIGFyZQ0KICAoaSkgZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBub19vZl9hc3NldHMgc2hvd3Mgc2ltaWxhciBwaWN0dXJlIGFzIHByb2R1Y3Rpb24gb3ZlciBhc3NldHMsIGJ1dCB3aXRoIHdpZGVyIHNwcmVhZCBmb3IgYXNzZXRzID4gMjANCiAgKGkpIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgbm9fb2ZfYXNzZXRzIGlzIHN1cnByaXNpbmdseSBkaWZmZXJlbnQgZnJvbSBmbGV4aWJsZV9mb3JtYXQgb3ZlciBhc3NldHMsIGFzIGl0IGlzIGluIHRoZSBiZWdpbm5pbmcgbW9yZSBzcHJlYWQgdG93YXJkIGhpZ2hlciAgICAgICAgICAgICAgIGNvbnRyaWJ1dGlvbiwgYnV0IGFmdGVyIGFzc2V0cyA+IDIwLCB0aGVyZSBzZWVtcyB0byBiZSBhIHRocmVzaG9sZCBhdCAxLjQsIHdoZXJlIG9ubHkgYSBmZXcgb3V0bGllcnMgZ28gYmV5b25kLCB0aG91Z2ggaXQgaXMgcmlzaW5nIHVudGlsIHRoaXMgKGZhc3QgcmVhY2hlZCkgcG9pbnQNCiAgKGkpIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBub19vZl9hc3NldHMgZG9lcyBhZ2FpbiBsb29rIHNpbWlsYXIgdG8gZmxleGlibGVfZm9ybWF0IG92ZXIgYXNzZXRzLCBzaW5jZSB0b3RhbCA9IGZsZXhpYmxlICsgcmlnaWQsIHRoaXMgbWVhbnMgdGhhdCBhYm92ZSAyMCBhc3NldHMsICAgICAgICAgICAgIGZsZXhpYmxlIGlzIGRvbWluYW50LCBidXQgYmVsb3cgdGhlcmUgaXMgYSB3aWRlciBzcHJlYWQgZHVlIHRvIHJpZ2lkX2Zvcm1hdA0KICAoaSkgdG90YWxfd2FzdGVfZGl2X3Byb2R1Y3Rpb24gb3ZlciBub19vZl9hc3NldHMgc2hvdyBhdCBsb3cgbnVtYmVyIG9mIGFzc2V0cyAoPDIwKSBhIHdpZGUgc3ByZWFkIHJhbmdpbmcgZnJvbSAwLjMgdG8gMS4wLCBidXQgYWJvdmUgdGhlcmUgc2VlbXMgdG8gYmUgc3RhYmxlIGF0IGFyb3VuZCAwLjQ1IHJhdGlvDQogICAgICAtPiBtYXliZSB0aGVyZSBhcmUgdHdvIGRpZmZlcmVudCBzdWItcG9wdWxhdGlvbnMgYmVoaW5kPw0KICAoaSkgd2l0aCBhIGJpZ2dlciBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzIGNvbWVzIHJlbGF0aXZlbHkgbGluZWFybHkgYSBiaWdnZXIgZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUsIGJ1dCBtb3N0IHByb2R1Y2VyIGhhdmUgYSBzbWFsbGVyIDMNCiAgKGkpIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyBzaG93cyBhZ2FpbiB0aGUgY2FwIGluIHJpZ2lkX2Zvcm1hdCBwYXJ0IG5vdCBncm93aW5nIGJleW9uZCAxLjMgd2l0aCBwcm9kdWN0aW9uLCBidXQgYWxzbyBhIHNlY29uZCAgICAgICAgIHRlbmRlbmN5IGluIHRoZSBiZWdpbm5pbmcgd2hlcmUgYSBsaW5lYXIgYmVoYXZpb3Igb2Ygc3Ryb25nIGdyb3dpbmcgcmlnaWRfZm9ybWF0IHN1Z2dlc3QgdGhhdCB0aGVyZSBtaWdodCBiZSB0d28gc3ViLXBvcHVsYXRpb25zDQogIChpKSB0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIG92ZXIgcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyBsb29rcyBwcmV0dHkgbXVjaCBsaW5lYXIsIHdpdGggYSBidWxrIG9mIGRhdGEgcG9pbnRzIGJlbG93IHByb2R1Y3Rpb24gPCAzDQogIChpKSBpbiB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbiBvdmVyIHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMgYmVsb3cgcHJvZHVjdGlvbiA8IDMgdGhlcmUgYXJlIHR3byBjbHVzdGVyIGFyb3VuZCAwLjQ1IGFuZCAxLjAsIGJleW9uZCBwcm9kdWN0aW9uID4gMyBpdCBzZWVtcyB0byBiZSBzdGFibGUgICAgICAgIGF0IDAuNQ0KICAoaSkgcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb3ZlciBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBzaG93cyB0aGUgcHJldmlvdXNseSBvYnNlcnZlZCBwaMOkbm9tZW5hLCBpKSB3aXRoIGdyb3dpbmcgZmxleGlibGVfZm9ybWF0LCByaWdpZF9mb3JtYXQgICAgICAgICAgYWxzbyBzdGFydCB0byBncm93IGEgbGl0dGxlIGJ1dCB0aGVuIHN0YXlzIGF0IGFyb3VuZCAxLjIsIGlpKSB0aGVyZSBpcyBvbmUgZ3JvdXAgdGhhdCBvbmx5IGdyb3dzIGluIHJpZ2lkX2Zvcm1hdCBhbmQgcHJvZHVjZSBhbG1vc3Qgbm8gZmxleGlibGVfZm9ybWF0DQogIChpKSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBvdmVyIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgc2hvd3MgYW4gYWxtb3N0IGxpbmVhciBpbmNyZWFzZSBpbiBmbGV4aWJsZV9mb3JtYXQgd2l0aCB0b3RhbF9jb250cmlidXRpb24sIGJ1dCBoZXJlIGFnYWluIHdlICAgICAgICAgIGhhdmUgYSBncm91cCB3aXRoIGFsbW9zdCBubyBmbGV4aWJsZV9mb3JtYXQgKHdoaWNoIG1lYW5zIHRoYXQgdGhleSBvbmx5IHByb2R1Y2UgcmlnaWRfZm9ybWF0KQ0KICAoaSkgdG90YWxfd2FzdGVfZGl2X3Byb2R1Y3Rpb24gb3ZlciBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBzaG93cyBhZ2FuaSB0cXdvIGNsdXN0ZXJzIG9uZSBhcm91bmQgdG90YWxfd2FzdGVfZGl2IDEuMCBhbmQgdGhlIG90aGVyIGFyb3VuZCAwLjQ1LCBhbmQgdGhhdCB0aGUgICAgICAgICAgICBoaWdoZXIgcmVnaW9ucyBvZiBmbGV4aWJsZV9mb3JtYXQgYXJlIG9ubHkgb3Z2dXBpZWQgYnkgYSBmZXcgcHJvZHVjZXJzIHdpdGggYSByYXRpb24gYXJvdW5kIDAuNDcgDQogIChpKSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBvdmVyIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgb25seSBhdCB0aGUgYmVnaW5uaW5nIHJpZ2lkIGZvcm1hdCBpcyBncm93aW5nIHdpdGggdG90YWxfY29udHJpYnV0aW9uLCBidXQgaXQgaXMgbm90IHJlYWxseSBncm93aW5nICAgICAgIGJleW9uZCAxLjMsIGZvciB0aGUgcmlnaWRfZm9ybWF0IG9ubHkgZ3JvdXAsIHRoZXJlIHRoZXJlIGlzIGEgYWxtb3N0IGxpbmVhciBncm91cA0KICAoaSkgbW9zdCBkYXRhIHBvaW50cyBsaWUgaW4gdGhlIHJhbmdlIHRvdGFsX3dhc3RlX2RpdiA8IDAuNyBhbmQgcmlnaWRfZm9ybWF0IDwgMC41LCBmb3IgdGhlIG91dGxpZXJzIHRoZXJlIGFyZSB0d28gZ3JvdXBzIG9uZSBhcm91bmQgcmF0aW8gMS4wIGFuZCBvbmUgd2l0aCBsb3dlciByYXRpbyBhcm91bmQgMC41DQogIChpKSB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbiBvdmVyIHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgc2hvd3MgYWdhaW4gdHdvIGdyb3VwcyBhcm91bmQgMS4wIGFuZCAwLjQ1IGFuZCBhIGNvbmNlbnRyYXRpb24gdW5kZXIgMC43NSB0b3RhbF9jb250cmlidXRpb24NCiAgKGkpIGNvbXBhcmluZyBmbGV4aWJsZV9mb3JtYXQgYW5kIHJpZ2lkX2Zvcm1hdCBvdmVyIHByb2R1Y3Rpb24gc2hvd3MgdXMgdGhhdCBmbGV4aWJsZV9mb3JtYXQgaXMgZ3Jvd2luZyBsaW5lYXJseSB3aGlsZSByaWdpZCBzdG9wcyBncm93aW5nIGxpbmVhcmx5IG1pZCB3YXkgYXQgcHJvZHVjdGlvbiA9IDYsIGJ1dCAgICAgICAgIHRoaXMgZ3Jvd3RoIG1pZ2h0IGJlIGRpc3R1cmJlZCBieSB0d28gZGlmZmVyZW50IHN1Yi1wb3B1bGF0aW9ucyBhbmQgaXMgZXhwZWN0ZWQgdG8gYmUgbXVjaCBsZXNzIHN0cm9uZyBhbmQgY2FwcGluZyBvdXQgZWFybGllciANCg0KYGBge3J9DQojIHR3byB2YXJpYWJsZXMsIGNvbnRpbnVvdXMgeCwgY29udGludW91cyB5LCBzaG93IHRyZW5kIGFuZCBkaXN0cmlidXRpb24NCm5hbWUgPSBjKCdwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzJywgJ3RvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnKQ0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHggPSBwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzLCB5ID0gdG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSwgdGV4dCA9IHBvbHltZXJfcHJvZHVjZXIpICU+JSBzZWxlY3QoeCwgeSwgdGV4dCkgDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fc21vb3RoLmh0bWwNCnBvaW50X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgICMgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUsIHNpemUgPSAxKSArDQogICAgZ2VvbV9ydWcoYWxwaGEgPSAwLjUpICsgIyB0d28gMWQgbWFyZ2luYWwgZGlzdHJpYnV0aW9ucywgZGlzcGxheSBpbmRpdmlkdWFsIGNhc2VzIHNvIGFyZSBiZXN0IHVzZWQgd2l0aCBzbWFsbGVyIGRhdGFzZXRzDQogICAgZ2VvbV9kZW5zaXR5XzJkKGFscGhhID0gMC4yLCBiaW5zID0gNCkgKyMgMkQga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbiB1c2luZyBNQVNTOjprZGUyZCgpIGFuZCBkaXNwbGF5IHRoZSByZXN1bHRzIHdpdGggY29udG91cnMNCiAgICBnZW9tX3Ntb290aChmaWxsID0gImdyZXk5MCIpICsgIyBhaWRzIHRoZSBleWUgaW4gc2VlaW5nIHBhdHRlcm5zIGluIHRoZSBwcmVzZW5jZSBvZiBvdmVycGxvdHRpbmcNCiAgICBnZW9tX3BvaW50KGFlcyh0ZXh0ID0gdGV4dCksIGFscGhhID0gMC43NSkgKyAjIHBvaW50IGdlb20gaXMgdXNlZCB0byBjcmVhdGUgc2NhdHRlcnBsb3RzDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJ0cmVuZCBvZiIsIG5hbWVbMl0sICJvdmVyIiwgbmFtZVsxXSwgc2VwPSIgIikpIA0KcG9pbnRfcGxvdCA8LSBnZ3Bsb3RseShwb2ludF9wbG90KSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFKSkNCg0KeF9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQp4X2RlbnNpdHlfcGxvdCA8LSBnZ3Bsb3RseSh4X2RlbnNpdHlfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KeV9kZW5zaXR5X3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHkpKSArDQogICAgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiKSArICMgZHJhd3Mga2VybmVsIGRlbnNpdHkgZXN0aW1hdGUsIHdoaWNoIGlzIGEgc21vb3RoZWQgdmVyc2lvbiBvZiB0aGUgaGlzdG9ncmFtDQogICAgIyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnlfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHlfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3F1YW50aWxlLmh0bWwNCnF1YWx0aWxlX3Bsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgIGdlb21fcXVhbnRpbGUoYWxwaGEgPSAwLjgpICsgIyBmaXRzIGEgcXVhbnRpbGUgcmVncmVzc2lvbiB0byB0aGUgZGF0YSBhbmQgZHJhd3MgdGhlIGZpdHRlZCBxdWFudGlsZXMgd2l0aCBsaW5lcw0KICAgIHRoZW1lX21pbmltYWwoKSANCnF1YWx0aWxlX3Bsb3QgPC0gZ2dwbG90bHkocXVhbHRpbGVfcGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgbWVyZ2UgZmlndXJlcyBpbnRvIG9uZSBwbG90LCB2aWEgc3VicGxvdHMsIGh0dHBzOi8vcGxvdGx5LXIuY29tL2FycmFuZ2luZy12aWV3cy5odG1sDQpzdWIxIDwtIHN1YnBsb3QoeF9kZW5zaXR5X3Bsb3QsIHBsb3RseV9lbXB0eSgpLCBwb2ludF9wbG90LCB5X2RlbnNpdHlfcGxvdCwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjE1LCAwLjg1KSwgd2lkdGhzID0gYygwLjksIDAuMSksIHNoYXJlWCA9IFRSVUUsIHNoYXJlWSA9IFRSVUUsIHRpdGxlWCA9IEZBTFNFLCB0aXRsZVkgPSBGQUxTRSkgJT4lIGxheW91dCgpDQpzdWIyIDwtIHN1YnBsb3QocXVhbHRpbGVfcGxvdCwgcGxvdGx5X2VtcHR5KCksIG1hcmdpbiA9IDAsIHdpZHRocyA9IGMoMC45LCAwLjEwKSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkNCmZpZyA8LSBzdWJwbG90KHN1YjEsIHN1YjIsIG5yb3dzID0gMiwgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC44LCAwLjIpLCBzaGFyZVggPSBUUlVFKSAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWVbMV0pLCB5YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lWzJdKSkNCiAgDQpmaWcNCmBgYA0KYGBge3J9DQojIHRocmVlIHZhcmlhYmxlcywgY29udGludW91cyB4LCB0d28gY29udGludW91cyB5LCBzaG93IHRyZW5kIGFuZCBkaXN0cmlidXRpb24NCm5hbWUgPSBjKCdwcm9kdWN0aW9uX29mX2luX3Njb3BlX3BvbHltZXJzJywgJ3JpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJywgJ2ZsZXhpYmxlX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJykNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh4ID0gcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycywgcmlnaWQgPSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSwgZmxleGlibGUgPSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdCh4LCByaWdpZCwgZmxleGlibGUpICU+JSBwaXZvdF9sb25nZXIoY29scyA9IGMoZmxleGlibGUscmlnaWQpKSAlPiUgcmVuYW1lKHkgPSB2YWx1ZSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9zbW9vdGguaHRtbA0KcG9pbnRfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHksIGNvbG91ciA9IG5hbWUpKSArDQogICAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsNCiAgICBnZW9tX3J1ZyhhbHBoYSA9IDAuNSkgKyAjIHR3byAxZCBtYXJnaW5hbCBkaXN0cmlidXRpb25zLCBkaXNwbGF5IGluZGl2aWR1YWwgY2FzZXMgc28gYXJlIGJlc3QgdXNlZCB3aXRoIHNtYWxsZXIgZGF0YXNldHMNCiAgICBnZW9tX2RlbnNpdHlfMmQoYWxwaGEgPSAwLjIsIGJpbnMgPSA0KSArIyAyRCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uIHVzaW5nIE1BU1M6OmtkZTJkKCkgYW5kIGRpc3BsYXkgdGhlIHJlc3VsdHMgd2l0aCBjb250b3Vycw0KICAgIGdlb21fc21vb3RoKGZpbGwgPSAiZ3JleTkwIikgKyAjIGFpZHMgdGhlIGV5ZSBpbiBzZWVpbmcgcGF0dGVybnMgaW4gdGhlIHByZXNlbmNlIG9mIG92ZXJwbG90dGluZw0KICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjc1KSArICMgcG9pbnQgZ2VvbSBpcyB1c2VkIHRvIGNyZWF0ZSBzY2F0dGVycGxvdHMNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUocGFzdGUoInRyZW5kIG9mIiwgbmFtZVsyXSwgIm92ZXIiLCBuYW1lWzFdLCBzZXA9IiAiKSkgDQpwb2ludF9wbG90IDwtIGdncGxvdGx5KHBvaW50X3Bsb3QpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UpKQ0KDQp4X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgY29sb3VyID0gbmFtZSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCnhfZGVuc2l0eV9wbG90IDwtIGdncGxvdGx5KHhfZGVuc2l0eV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQp5X2RlbnNpdHlfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geSwgY29sb3VyID0gbmFtZSkpICsNCiAgICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIpICsgIyBkcmF3cyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSwgd2hpY2ggaXMgYSBzbW9vdGhlZCB2ZXJzaW9uIG9mIHRoZSBoaXN0b2dyYW0NCiAgICAjIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KeV9kZW5zaXR5X3Bsb3QgPC0gZ2dwbG90bHkoeV9kZW5zaXR5X3Bsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXVhbnRpbGUuaHRtbA0KcXVhbHRpbGVfcGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geCwgeSA9IHksIGNvbG91ciA9IG5hbWUpKSArDQogICAgZ2VvbV9xdWFudGlsZShhbHBoYSA9IDAuOCkgKyAjIGZpdHMgYSBxdWFudGlsZSByZWdyZXNzaW9uIHRvIHRoZSBkYXRhIGFuZCBkcmF3cyB0aGUgZml0dGVkIHF1YW50aWxlcyB3aXRoIGxpbmVzDQogICAgdGhlbWVfbWluaW1hbCgpIA0KcXVhbHRpbGVfcGxvdCA8LSBnZ3Bsb3RseShxdWFsdGlsZV9wbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBtZXJnZSBmaWd1cmVzIGludG8gb25lIHBsb3QsIHZpYSBzdWJwbG90cywgaHR0cHM6Ly9wbG90bHktci5jb20vYXJyYW5naW5nLXZpZXdzLmh0bWwNCnN1YjEgPC0gc3VicGxvdCh4X2RlbnNpdHlfcGxvdCwgcGxvdGx5X2VtcHR5KCksIHBvaW50X3Bsb3QsIHlfZGVuc2l0eV9wbG90LCBucm93cyA9IDIsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuMTUsIDAuODUpLCB3aWR0aHMgPSBjKDAuOSwgMC4xKSwgc2hhcmVYID0gVFJVRSwgc2hhcmVZID0gVFJVRSwgdGl0bGVYID0gRkFMU0UsIHRpdGxlWSA9IEZBTFNFKSAlPiUgbGF5b3V0KCkgJT4lIGhpZGVfbGVnZW5kKCkNCnN1YjIgPC0gc3VicGxvdChxdWFsdGlsZV9wbG90LCBwbG90bHlfZW1wdHkoKSwgbWFyZ2luID0gMCwgd2lkdGhzID0gYygwLjksIDAuMTApLCB0aXRsZVggPSBGQUxTRSwgdGl0bGVZID0gRkFMU0UpICU+JSBsYXlvdXQoKQ0KZmlnIDwtIHN1YnBsb3Qoc3ViMSwgc3ViMiwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjgsIDAuMiksIHNoYXJlWCA9IFRSVUUpICU+JSBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZVsxXSksIHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlKG5hbWVbMl0sICI8YnI+IiwgbmFtZVszXSwgc2VwPSIiKSkpIA0KICANCmZpZw0KYGBgDQoNCg==